package com.insight.controller;

import com.insight.entity.MetadataColumn;
import com.insight.entity.MetadataTable;
import com.insight.repository.MetadataTableRepository;
import com.insight.service.MetadataCacheService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.Min;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

/**
 * T106: MetadataController REST API实现
 * 元数据查询与搜索REST API
 *
 * 端点列表:
 * - GET  /api/v1/metadata/tables/search - 表名搜索
 * - GET  /api/v1/metadata/tables/{id} - 获取表详情
 * - GET  /api/v1/metadata/tables/{id}/columns - 获取表的列
 * - GET  /api/v1/metadata/tables/fulltext - 全文搜索表
 * - GET  /api/v1/metadata/columns/search - 字段名搜索
 * - GET  /api/v1/metadata/columns/datatype - 数据类型筛选
 * - GET  /api/v1/metadata/tables/datasource/{id} - 按数据源查询表
 * - GET  /api/v1/metadata/columns/table/{id} - 按表ID查询列
 * - POST /api/v1/metadata/cache/evict/all - 清除所有缓存
 * - POST /api/v1/metadata/cache/evict/search - 清除搜索缓存
 * - POST /api/v1/metadata/cache/evict/query - 清除查询缓存
 *
 * @author Insight Team
 */
@Slf4j
@RestController
@RequestMapping("/api/v1/metadata")
@RequiredArgsConstructor
@Validated
@Tag(name = "元数据查询与搜索", description = "提供元数据搜索、查询和缓存管理功能")
public class MetadataController {

    private final MetadataCacheService cacheService;
    private final MetadataTableRepository tableRepository;

    // ==================== 搜索端点 ====================

    /**
     * 根据表名搜索表元数据
     * US4场景1: 表名关键字搜索
     *
     * @param keyword 搜索关键词(必填)
     * @param page    页码(从0开始,默认0)
     * @param size    每页大小(默认10)
     * @return 表元数据分页结果
     */
    @GetMapping("/tables/search")
    @Operation(summary = "表名搜索", description = "根据表名关键词搜索表元数据,支持模糊匹配。keyword为空时返回所有表。")
    public ResponseEntity<Page<MetadataTable>> searchTablesByName(
            @Parameter(description = "搜索关键词(为空时返回所有表)", required = false)
            @RequestParam(required = false, defaultValue = "") String keyword,
            @Parameter(description = "页码(从0开始)")
            @RequestParam(defaultValue = "0") @Min(0) int page,
            @Parameter(description = "每页大小")
            @RequestParam(defaultValue = "10") @Min(1) int size) {

        log.info("Searching tables by name: keyword='{}', page={}, size={}", keyword, page, size);

        Pageable pageable = PageRequest.of(page, size);

        // 当keyword为空时,返回所有表
        Page<MetadataTable> result;
        if (keyword == null || keyword.trim().isEmpty()) {
            log.debug("Empty keyword, returning all tables");
            result = cacheService.queryAllTables(pageable);
        } else {
            result = cacheService.searchTablesByName(keyword, pageable);
        }

        return ResponseEntity.ok(result);
    }

    /**
     * 全文搜索表元数据
     * 使用BM25算法进行相关性排序
     *
     * @param keyword 搜索关键词(必填)
     * @param page    页码(从0开始,默认0)
     * @param size    每页大小(默认10)
     * @return 表元数据分页结果
     */
    @GetMapping("/tables/fulltext")
    @Operation(summary = "全文搜索表", description = "使用BM25算法进行全文搜索,按相关性排序")
    public ResponseEntity<Page<MetadataTable>> searchTablesByFullText(
            @Parameter(description = "搜索关键词", required = true)
            @RequestParam(required = true) String keyword,
            @Parameter(description = "页码(从0开始)")
            @RequestParam(defaultValue = "0") @Min(0) int page,
            @Parameter(description = "每页大小")
            @RequestParam(defaultValue = "10") @Min(1) int size) {

        log.info("Full-text searching tables: keyword={}, page={}, size={}", keyword, page, size);

        Pageable pageable = PageRequest.of(page, size);
        Page<MetadataTable> result = cacheService.searchTablesByFullText(keyword, pageable);

        return ResponseEntity.ok(result);
    }

    /**
     * 根据列名搜索列元数据
     * US4场景2: 字段名搜索
     *
     * @param keyword 搜索关键词(必填)
     * @param page    页码(从0开始,默认0)
     * @param size    每页大小(默认10)
     * @return 列元数据分页结果
     */
    @GetMapping("/columns/search")
    @Operation(summary = "字段名搜索", description = "根据字段名关键词搜索列元数据,展示所有包含该字段的表")
    public ResponseEntity<Page<MetadataColumn>> searchColumnsByName(
            @Parameter(description = "搜索关键词", required = true)
            @RequestParam(required = true) String keyword,
            @Parameter(description = "页码(从0开始)")
            @RequestParam(defaultValue = "0") @Min(0) int page,
            @Parameter(description = "每页大小")
            @RequestParam(defaultValue = "10") @Min(1) int size) {

        log.info("Searching columns by name: keyword={}, page={}, size={}", keyword, page, size);

        Pageable pageable = PageRequest.of(page, size);
        Page<MetadataColumn> result = cacheService.searchColumnsByName(keyword, pageable);

        return ResponseEntity.ok(result);
    }

    /**
     * 根据数据类型筛选列元数据
     * US4场景3: 数据类型筛选
     *
     * @param type 数据类型(必填,例如: VARCHAR, BIGINT, INT)
     * @param page 页码(从0开始,默认0)
     * @param size 每页大小(默认10)
     * @return 列元数据分页结果
     */
    @GetMapping("/columns/datatype")
    @Operation(summary = "数据类型筛选", description = "根据数据类型筛选列元数据,展示所有使用该数据类型的字段")
    public ResponseEntity<Page<MetadataColumn>> searchColumnsByDataType(
            @Parameter(description = "数据类型(例如: VARCHAR, BIGINT)", required = true)
            @RequestParam(name = "type", required = true) String dataType,
            @Parameter(description = "页码(从0开始)")
            @RequestParam(defaultValue = "0") @Min(0) int page,
            @Parameter(description = "每页大小")
            @RequestParam(defaultValue = "10") @Min(1) int size) {

        log.info("Searching columns by data type: dataType={}, page={}, size={}", dataType, page, size);

        Pageable pageable = PageRequest.of(page, size);
        Page<MetadataColumn> result = cacheService.searchColumnsByDataType(dataType, pageable);

        return ResponseEntity.ok(result);
    }

    // ==================== 查询端点 ====================

    /**
     * 获取单个表的详细信息
     *
     * @param tableId 表ID(必填)
     * @return 表元数据详情
     */
    @GetMapping("/tables/{tableId}")
    @Operation(summary = "获取表详情", description = "根据表ID获取单个表的详细元数据信息")
    public ResponseEntity<MetadataTable> getTableById(
            @Parameter(description = "表ID", required = true)
            @PathVariable @Min(1) Long tableId) {

        log.info("Getting table detail by ID: tableId={}", tableId);

        // 直接从repository查询
        MetadataTable table = tableRepository.findById(tableId)
                .orElseThrow(() -> new RuntimeException("Table not found with id: " + tableId));

        return ResponseEntity.ok(table);
    }

    /**
     * 获取指定表的所有列
     *
     * @param tableId 表ID(必填)
     * @param page    页码(从0开始,默认0)
     * @param size    每页大小(默认20)
     * @return 列元数据分页结果
     */
    @GetMapping("/tables/{tableId}/columns")
    @Operation(summary = "获取表的列信息", description = "根据表ID获取该表的所有列元数据(分页)")
    public ResponseEntity<Page<MetadataColumn>> getColumnsByTableId(
            @Parameter(description = "表ID", required = true)
            @PathVariable @Min(1) Long tableId,
            @Parameter(description = "页码(从0开始)")
            @RequestParam(defaultValue = "0") @Min(0) int page,
            @Parameter(description = "每页大小")
            @RequestParam(defaultValue = "20") @Min(1) int size) {

        log.info("Getting columns by table ID: tableId={}, page={}, size={}", tableId, page, size);

        Pageable pageable = PageRequest.of(page, size);
        Page<MetadataColumn> result = cacheService.queryColumnsByTableId(tableId, pageable);

        return ResponseEntity.ok(result);
    }

    /**
     * 查询指定数据源的所有表
     * US4场景4: 组合筛选(数据源维度)
     *
     * @param dataSourceId 数据源ID(必填)
     * @param page         页码(从0开始,默认0)
     * @param size         每页大小(默认10)
     * @return 表元数据分页结果
     */
    @GetMapping("/tables/datasource/{dataSourceId}")
    @Operation(summary = "按数据源查询表", description = "查询指定数据源的所有表元数据")
    public ResponseEntity<Page<MetadataTable>> queryTablesByDataSourceId(
            @Parameter(description = "数据源ID", required = true)
            @PathVariable @Min(1) Long dataSourceId,
            @Parameter(description = "页码(从0开始)")
            @RequestParam(defaultValue = "0") @Min(0) int page,
            @Parameter(description = "每页大小")
            @RequestParam(defaultValue = "10") @Min(1) int size) {

        log.info("Querying tables by data source ID: dataSourceId={}, page={}, size={}",
                dataSourceId, page, size);

        Pageable pageable = PageRequest.of(page, size);
        Page<MetadataTable> result = cacheService.queryTablesByDataSourceId(dataSourceId, pageable);

        return ResponseEntity.ok(result);
    }

    /**
     * 查询指定表的所有列
     * US4场景4: 组合筛选(表维度)
     *
     * @param tableId 表ID(必填)
     * @param page    页码(从0开始,默认0)
     * @param size    每页大小(默认10)
     * @return 列元数据分页结果
     */
    @GetMapping("/columns/table/{tableId}")
    @Operation(summary = "按表ID查询列", description = "查询指定表的所有列元数据")
    public ResponseEntity<Page<MetadataColumn>> queryColumnsByTableId(
            @Parameter(description = "表ID", required = true)
            @PathVariable @Min(1) Long tableId,
            @Parameter(description = "页码(从0开始)")
            @RequestParam(defaultValue = "0") @Min(0) int page,
            @Parameter(description = "每页大小")
            @RequestParam(defaultValue = "10") @Min(1) int size) {

        log.info("Querying columns by table ID: tableId={}, page={}, size={}", tableId, page, size);

        Pageable pageable = PageRequest.of(page, size);
        Page<MetadataColumn> result = cacheService.queryColumnsByTableId(tableId, pageable);

        return ResponseEntity.ok(result);
    }

    // ==================== 缓存管理端点 ====================

    /**
     * 清除所有缓存
     * 用于元数据采集完成后刷新缓存
     *
     * @return 204 No Content
     */
    @PostMapping("/cache/evict/all")
    @Operation(summary = "清除所有缓存", description = "清除所有元数据搜索和查询缓存")
    public ResponseEntity<Void> evictAllCaches() {
        log.info("Evicting all metadata caches");
        cacheService.evictAllCaches();
        return ResponseEntity.noContent().build();
    }

    /**
     * 清除搜索缓存
     * 用于搜索索引重建后刷新缓存
     *
     * @return 204 No Content
     */
    @PostMapping("/cache/evict/search")
    @Operation(summary = "清除搜索缓存", description = "清除元数据搜索缓存")
    public ResponseEntity<Void> evictSearchCache() {
        log.info("Evicting metadata search cache");
        cacheService.evictSearchCache();
        return ResponseEntity.noContent().build();
    }

    /**
     * 清除查询缓存
     * 用于元数据更新后刷新查询缓存
     *
     * @return 204 No Content
     */
    @PostMapping("/cache/evict/query")
    @Operation(summary = "清除查询缓存", description = "清除元数据查询缓存")
    public ResponseEntity<Void> evictQueryCache() {
        log.info("Evicting metadata query cache");
        cacheService.evictQueryCache();
        return ResponseEntity.noContent().build();
    }
}
